Git vertakkingen samenvoegen
Met git merge
zet je een van een afgetakte geschiedenis weer bij elkaar. Het git merge
commando integreert een onafhankelijke ontwikkelingslijn, die je met git branch
hebt gemaakt, in één enkele tak.
Alle opdrachten hieronder voegen aftakkingen weer samen in de in de in gebruikzijnde tak. De in gebruik zijnde tak zal worden bijgewerkt om de fusie bevatten, maar de doel-tak zal ongewijzigd zijn. Dit betekent dit git merge
vaak gebruikt wordt in combinatie met git checkout
om een in gebruik zijnde tak te selecteren en git branch -d
voor het verwijderen van de verouderde doel-tak.
Gebruik
Voeg de opgegeven vertakking samen met de in gebruik zijnde vertakking:
git merge <branch>
Voeg de opgegeven vertakking samen met de in gebruik zijnde vertakking en genereer een merge commit. Op die manier worden al samenvoegingen gedocumenteerd in je bewaarplaats.
Zodra je klaar bent met het ontwikkelen van een functie in een geïsoleerde tak, moet je die kunnen invoegen in de hoofdtak. Afhankelijk van de structuur van je repository, beschikt Git over een aantal algoritmes om dit te bereiken:
- een fast-forward samenvoeging of
- een 3-weg merge.
Een fast-forward samenvoeging kan optreden wanneer er een lineair pad bestand dat gaat van de huidige tak-tip naar de doel-tak. In plaats van de vertakkingen echt samen te voegen gaat Git om de geschiedenis van beide vertakkingen samen te voegen, de huidige branch tip verplaatsen naar de doel-tak-tip. Dit combineert effectief de geschiedenissen, omdat alle commits bereikbaar zijn vanaf de doel-tak via de huidige tak. Bijvoorbeeld, een fast forward samenvoeging van bepaalde-functie in de master ziet er als volgt uit:
als de takken zijn gedivergeerd, is een fast-forward samenvoeging niet mogelijk want er is geen lineair pad naar de doel-tak, Git heeft dan geen andere keuze dan ze samen te voegen via een 3-weg merge. 3-weg merge maakt gebruik van een speciale commit om de twee geschiedenissen samen te voegen. De naamgeving komt van het feit dat Git drie commits gebruikt om de merge commit te genereren:
- de twee eindpunten van de vertakkingen;
- hun gemeenschappelijke voorouder;
Conflicten oplossen
Als in de twee vertakkingen, die je probeert samen te voegen, hetzelfde deel van hetzelfde bestand gewijzigd is, zal Git niet in staat zijn om erachter te komen welke versie voorrang heeft.
Wanneer een dergelijke situatie zich voordoet, stopt de merge net voor de merge commit, zodat je de conflicten handmatig kan oplossen.
Het voordeel van Git's bewerken / verzamelen / neerleggen workflow bestaat erin dat je git status
kan uitvoeren om te zien welke conflicten je manueel moet oplossen vooraleer te kunnensamenvoegen.
Bijvoorbeeld, als beide takken hetzelfde gedeelte van Vera.txt gewijzigd hebben, zie je zoiets
# On branch master # Unmerged paths: # (use "git add/rm ..." as appropriate to mark resolution) # # both modified: Vera.txt #
Vervolgens kan je de bestanden openen en de nodige wijzigingen aanbrengen om de samanvoeging naar wens te kunnen uitvoeren. Wanneer je klaar bent om de samenvoeging uit te voeren hoef je alleen maar een git add
uit te voeren op het conflicterende bestand(en) om Git op de hoogte te brengen dat de conflicten zijn opgelost.
Vervolgens voer je een normale git commit
uit om de merge commit te genereren. DAT komt op precies hetzelfde neer als een uitvoeren van een gewone commit. Dat betekent dat de doorsnee ontwikkelaars heel gemakkelijk hun eigen samenvoegingen kunnen beheren.
Conflicten treden alleen bij een 3-merge op. Het is onmogelijk om conflicterende wijzigingen in een fast-forward-merge te hebben.
Voorbeeld
fast-forward samenvoegen
Op het moment dat ik dit voorbeeld maak, ziet mijn projectgeschiedenis er zo uit:
C:\myap>git log --oneline 44430ac Vondel en Engelman meest volledig eae692f Revert "Revert "Vondel eerste versie toegevoegd"" 7b57a41 Revert "Vondel eerste versie toegevoegd" 9af1508 Vera eerste versie hersteld f2afd87 Vondel eerste versie toegevoegd 76367c9 Vera derde versie ac43111 Vera tweede versie b3a2046 Vera eerste versie
We gaan een vertakking maken omdat ik me nu met een andere dichter ga bezighouden, namelijk Hendrik Marsman. We beginnen met een nieuwe aftakking te maken en onze werkmap daarmee te laten overkomen:
C:\myap>git branch * master C:\myap>git branch marsman C:\myap>git branch marsman * master C:\myap>git checkout marsman Switched to branch 'marsman' C:\myap>git branch * marsman master C:\myap>
We maken een bestand met de naam Regen.txt en plaatsen daarin de volgende tekst:
Regen
De regen valt in de nacht
in het dal, tussen donkere bergen;
uw haar en uw handen zijn zacht,
maar waar, waar moet ik mij bergen
in die laatste verwilderde nacht
als de hitte de overmacht
zal verkrijgen op al het zijnde
en de dood in de vlammen ons wacht.
nu kan ik nog wel bij u schuilen
maar hoe zal het zijn in die nacht
als de winden als wolven huilen
en de eeuwige vierschaar ons wacht.
o God! sta ons bij in het einde —
wij zelf zijn zonder kracht.Hendrik Marsman, Porta Nigra (1934)
We inspecteren onze werkmap met git status
. We zien dat we in de marsman tak zitten en dat Regen.txt nog niet aan de verzamelplaats is toegevoegd. Dat doen we nu en leggen de wijziging neer in de repo met een commit:
C:\myap>git status On branch marsman Untracked files: (use "git add <file>..." to include in what will be committed) Regen.txt nothing added to commit but untracked files present (use "git add" to track) C:\myap>git add Regen.txt C:\myap>git commit -m "Het gedicht Regen van Hendrik Marsman is toegevoegd." [marsman 0e95d2f] Het gedicht Regen van Hendrik Marsman is toegevoegd. 1 file changed, 19 insertions(+) create mode 100644 Regen.txt
Zoals je hieronder ziet werden alle commits van de tak, waarvan afgesplitst werd, mee overgezet naar de nieuwe tak:
C:\myap>git log --oneline
0e95d2f Het gedicht Regen van Hendrik Marsman is toegevoegd.
44430ac Vondel en Engelman meest volledig
eae692f Revert "Revert "Vondel eerste versie toegevoegd""
7b57a41 Revert "Vondel eerste versie toegevoegd"
9af1508 Vera eerste versie hersteld
f2afd87 Vondel eerste versie toegevoegd
76367c9 Vera derde versie
ac43111 Vera tweede versie
b3a2046 Vera eerste versie
C:\myap>
Maar de master tak is niet op de hoogte van de commit in de nieuwe marsman
tak:
C:\myap>git status On branch marsman nothing to commit, working directory clean C:\myap>git checkout master Switched to branch 'master' C:\myap>dir Volume in drive C is Windows Volume Serial Number is C6F4-3FE3 Directory of C:\myap 29/01/2017 13:11 <DIR> . 29/01/2017 13:11 <DIR> .. 25/01/2017 14:39 14 .gitignore 29/01/2017 12:42 218 Vera.txt 28/01/2017 13:09 265 Vondel.txt 3 File(s) 497 bytes 2 Dir(s) 100 369 092 608 bytes free C:\myap>git log --oneline 44430ac Vondel en Engelman meest volledig eae692f Revert "Revert "Vondel eerste versie toegevoegd"" 7b57a41 Revert "Vondel eerste versie toegevoegd" 9af1508 Vera eerste versie hersteld f2afd87 Vondel eerste versie toegevoegd 76367c9 Vera derde versie ac43111 Vera tweede versie b3a2046 Vera eerste versie
Ik wil nu de wijzigingen die zijn aangebracht in de marsman
vertakking samenvoegen met de master
tak. Zoals je hierboven ziet staat het bestand Regen.txt niet in de master
en ook niet de laatste commit, die werd uitgevoerd in marsman
vertakking.
We springen eerst naar de marsman
tak om de id van de laatste commit op te halen;
C:\myap>git checkout marsman Switched to branch 'marsman' C:\myap>git log --oneline 0e95d2f Het gedicht Regen van Hendrik Marsman is toegevoegd. 44430ac Vondel en Engelman meest volledig eae692f Revert "Revert "Vondel eerste versie toegevoegd"" 7b57a41 Revert "Vondel eerste versie toegevoegd" 9af1508 Vera eerste versie hersteld f2afd87 Vondel eerste versie toegevoegd 76367c9 Vera derde versie ac43111 Vera tweede versie b3a2046 Vera eerste versie
Vervolgens keren we terug naar de master
tak en voeren de merge uit:
C:\myap>git checkout master Switched to branch 'master' C:\myap>git merge 0e95d2f Updating 44430ac..0e95d2f Fast-forward Regen.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Regen.txt C:\myap>